Tools Plus gives your application the ability to change the cursor’s shape as required. The five standard Macintosh cursors are immediately available for use, though you may create your own custom cursors by using a resource editor such as Apple’s ResEdit. Cursors are identified by a number (0 through 4 are reserved for the standard cursors), and are best referenced by their constants, as indicated below:
(0) arrowCursor
(1) iBeamCursor
(2) crossCursor
(3) plusCursor
(4) watchCursor
A cursor’s shape can be changed as required by using the CursorShape procedure.
Three additional features have been added which make the cursor an integral part of Tools Plus:
• The cursor changes shape automatically depending on its position on
the screen and its orientation on the active window(s), including
the tool bar and floating palettes.
• Tools Plus recognizes that the watchCursor is an indicator of a
lengthy process, and acts accordingly.
• When the watchCursor is displayed, you can have an animated cursor
similar to the Finder’s spinning wrist watch.
Automatic Cursor Changes
````````````````````````
The cursor changes shape automatically only if your application has not set the watchCursor. If it has, see “The Watch Cursor” below. Each time that your application calls PollSystem, the cursor’s position is checked and changed if necessary. The change is in accordance to the following rules:
(1) If no windows are open, or if a desk accessory is the active window, the cursor is displayed as the standard Macintosh arrow. Desk accessories can manipulate the cursor as they see fit.
When your application has an active standard window, and/or open tool bar and/or floating palette…
(2) While the cursor is outside of the active window(s), it is displayed as the standard Macintosh arrow.
(3) While the cursor is in a window’s title bar (including the close box and zoom box), or in a documents “size box,” it is displayed as the standard Macintosh arrow.
When the cursor is within one of your application’s active window’s content area…
(4) When a cursor is within any editing field on a modeless window, it is displayed as an I-beam.
(5) When the cursor is outside all editing fields in a modeless window, or anywhere within a modal window, then it is displayed as the standard Macintosh arrow.
(6) If the window is using a Cursor Table, the table’s default cursor is displayed when the cursor is not in any of the zones but within the window’s content region. When the cursor enters one of the zones, it changes to the shape specified for that zone. See “The Cursor Table” for details.
Note: The cursor will not change while a drag is in progress (i.e.
pressing and holding the mouse button). This also includes moving
a scroll bar’s thumb, or clicking and holding a scroll bar’s up
arrow, “page up” region, down arrow, or “page down” region.
The Watch Cursor
````````````````
The watch cursor is used to indicate a long wait, such as when a lengthy process is being conducted or when printing is being done. Your application can display the watch cursor by using the CursorShape procedure.
While the watch cursor is displayed, your application may choose not to call PollSystem, since it doesn’t care what the user is doing and will want to ignore mouse clicks and typing anyway. Unfortunately, this does not give the user the opportunity to halt a lengthy process, nor does it give other applications running under MultiFinder or System 7 any processing time. The watch cursor solves this dilemma by making Tools Plus shift into a busy mode, where it filters out (discards) unwanted events.
As soon as the watch cursor is displayed, the caret in an active editing field stops flashing. The watch cursor will not be automatically altered as described in Automatic Cursor Changes until your application changes the cursor to some other shape. When PollSystem is called, all mouse clicks and typing are ignored, except Command-. which tells your application to halt the process. This lets your application call PollSystem regularly while it is busy conducting a lengthy task, knowing that any key or mouse event it receives is meaningful (i.e. halt the process). Your application may choose not to call PollSystem or to ignore the Command-. key if it’s is busy only for a short time.
When your application is finished its lengthy process, it can either change the cursor itself, or call ResetCursor which changes the cursor to its appropriate shape according to its position on the screen.
Advanced programmers can take “being busy” one step further. While your application is busy, it can display a modal window with a descriptive message and a “Cancel” push button. By setting the WatchCursorButtons procedure on, the watch cursor will have the ability to click any push button on the active window. Furthermore, if a button has been designated as the “default,” it is activated by pressing the Return or Enter key. A good illustration of this is in a word processing program that has “Pause” and “Cancel” buttons available during printing. When “Pause” is clicked, printing is temporarily suspended and the button changes to “Resume.” Clicking “Resume” continues the printing process and switches the button back to “Pause.” The “Cancel” button has the same affect as typing Command-. to halt the process. Note that typing Command-. will always be reported by PollSystem. Remember to switch the WatchCursorButtons procedure off when you no longer need it, or else the watch cursor will be able to indiscriminately select buttons on any active window.
See PollSystem for details pertaining to the watch cursor and events that are reported while the watch cursor is displayed.
Warning: If your application is running under MultiFinder or System 7,
it is possible to switch to another application while a watch
cursor is displayed unless your active window is of type
dBoxProc.
Starting your application
`````````````````````````
When starting your application, you may notice a difference between working in the THINK Pascal environment and your finished (double-clickable) application. THINK Pascal changes the cursor to a cross-hair, whereas any program launched from The Finder will have a watch cursor.
To Tools Plus, both of these cursors are treated the same way: the cursor is considered to be undefined. This is not a problem because PollSystem will change the cursor’s shape as required. In applications launched by The Finder, this undefined cursor does not behave like a watch cursor to prevent clicking and typing. Your application must explicitly use the CursorShape routine to set the watch cursor to a true busy state.
The Cursor Table
````````````````
A cursor table is comprised of one or more cursor zones, each being a region in a window’s local co-ordinates. When the cursor enters a cursor zone, it changes to the shape specified for that zone. Cursor tables are created independently of windows, thereby allowing many windows to use the same cursor table.
A cursor table is created by the NewCursorTable procedure. Each cursor table is referenced by a unique number called the cursor table number. This number is specified when the cursor table is created, and refers to the specific table until it is deleted. A default cursor shape is specified for the entire table, in case the cursor does not fall into any of the table’s zones.
Cursor zones are added to the table by using the CursorZone (CursorZoneRect or CursorZoneRgn) procedure. Each zone specifies a region in a window’s local co-ordinates, and the type of cursor that is displayed within those co-ordinates. Individual cursor zones are deleted by using the DeleteCursorZone procedure. Cursor zones can be added or deleted in any order.
The UseCursorTable procedure is used to make a window use a specific cursor table. The window will continue to use the same cursor table until it is closed or the cursor table is deleted. If the cursor table is changed in any way, all windows using that table will incorporate those changes.
When a cursor table is no longer required, it is deleted by the DeleteCursorTable procedure.
When the cursor is outside all editing fields in a modeless window, or anywhere within a modal window, the window’s cursor table is checked to see if the cursor is in any of the table’s zones (see “Automatic Cursor Changes”). Cursor zones are checked sequentially starting at the lowest numbered zone. If the cursor’s “hot spot” is within a zone’s region, the cursor’s shape changes to the cursor defined for that zone. Otherwise, it is drawn using the table’s default cursor.
Any changes made to cursor tables or zones (such as adding, changing, or deleting) which affect the active window will be in effect the next time PollSystem is called.
Advanced Features
`````````````````
Cursor zones can be made to “overlap” one another The lowest numbered zone that encloses the cursor is the containing zone, even if another higher numbered zone encloses the lower numbered zone. This is useful if you want to have several smaller zones on top of a large one. Zones can also be considered “click sensitive.” You can determine if a click occurred in any cursor zone on the current window by using the FindCursorZone procedure and handing it the click’s location. FindCursorZone returns the first zone number in the current window that contains the specified point. By doing this, your application can treat icons or pictures as click-sensitive objects (like buttons).
Note: Cursor tables, and specifically the cursor zones’ co-ordinates,
are not changed automatically. This is an important consideration
when a window’s size is altered. Your application must maintain
cursor zones as required. Keep in mind that several windows may
be sharing the same cursor table.
Cursor Animation
````````````````
Tools Plus provides cursor animation, a process where the cursor changes over time. The good example of an animated cursor is System 7’s Finder. It displays a wrist watch whose minute hand moves clockwise while the Finder copies files. To animate a cursor, you will need to be familiar with a resource editor such as Apple’s ResEdit.
First, create the cursors (CURS resources) you need for your animation. One of the demo samples uses the system’s watch cursor (ID=4), plus seven custom cursors whose second hand is in a different position (remember: when creating cursors, used IDs 128 or higher).
Second, create an ‘acur’ resource with an ID of 128 or higher. The acur resource, when included in your application, tells Tools Plus which cursors to use and how quickly they should be animated.
‘Number of “frames” (cursors)’ specifies the number of cursors you use in a single cycle of the animation sequence.
‘Used a “frame” counter’ specifies the time in clock ticks between frames (cursors). A clock tick is 1/60 of a second.
The ‘‘CURS’ Resource Id section’ is repeated once for each cursor frame in the sequence. It specifies the cursor ID used per frame.
When your application calls CursorShape(watchCursor), the watch cursor is immediately displayed. Any time thereafter when your application calls PollSystem, it automatically steps through the animation sequence at the specified frame rate.
If CursorShape(watchCursor) is called again, it manually advances the cursor animation to the next step. If you have an animated cursor that is not a wrist watch (perhaps it is the spinning beach ball used in many applications), your acur resource should exclude the watch cursor.
Tools Plus includes several complete sets of animated cursors (including all cursor resources and the matching acur resource) in the “Optional Resources” folder. You may include any one of these sets in your application.
Warning: Do not modify or delete your acur resource during your
application. Tools Plus checks for availability and integrity
of the acur resource when InitToolsPlus is called at the
beginning of your program.
Handling Cursors
````````````````
The cursor can be set to any shape by calling the CursorShape procedure. Using PollSystem automatically changes the cursor’s shape as described in Automatic Cursor Changes using a cursor table if one has been assigned to the active window. Whenever your application sets the watchCursor, PollSystem filters out unwanted typing and mouse clicks. Filtering continues until your application resets the cursor by using ResetCursor, or changes the cursor by using the CursorShape routine.
The cursor is changed to the shape specified by CursorType. The five standard Macintosh cursors defined below are always available to your application. Additional cursors can be used, providing you create these resources and add them to your application. If CursorType is not an existing cursor reference number, the cursor is changed to the standard Macintosh arrow. This procedure displays the cursor in case it has been hidden by HideCursor or ObscureCursor.
When the watch cursor is displayed, Tools Plus shifts into a busy mode where it filters out (discards) unwanted events such as the user typing or clicking the mouse. Use ResetCursor to conclude the busy mode, or simply change the cursor to anything other than the watch. There is a section at the beginning of this chapter that details the watch cursor. Also see the WatchCursorButtons procedure which disallows or allows a watch cursor to click push buttons.
If your application calls CursorShape(watchCursor) when the watch cursor is already displayed, and your application has an acur resource (for cursor animation), then the cursor changes shape by advancing to the next frame in your cursor animation sequence.
Note: If you specify any cursor other than the watchCursor, it will
automatically be reset (as defined in “automatic cursor changes”
earlier in this chapter) the next time you get an event by calling
PollSystem. If you want the window to have a different default
cursor, or to display a specific cursor within a certain area, see
the section on The Cursor Table earlier in this chapter.
CONST {Cursor Types }
arrowCursor =0; {the standard Macintosh arrow }
iBeamCursor =1; {text insertion I-beam }
crossCursor =2; {cross-hair }
plusCursor =3; {select cells in structured documents }
watchCursor =4; {to indicate a long wait }
Warning: The InitCursor procedure must not be called at any time by your
Reset the cursor to its correct shape according to its orientation to the active window.
pascal void ResetCursor(void);
procedure ResetCursor;
After calling this routine, the cursor’s shape automatically changes according to the rules stated in Automatic Cursor Changes. Call ResetCursor to negate the effects of CursorShape(watchCursor).
CursorTable specifies the cursor table number (from 1 to 255) that is created. Your application will reference the cursor table by this number. If a cursor table has been previously created using the same number, it is deleted along with its zones. Any windows using the deleted table are reset to not reference a cursor table.
CursorType specifies the default cursor shape for the table. It is the shape the cursor takes when it is within the window’s region, but outside editing fields and cursor zones. If watchCursor is specified for this value, Tools Plus changes it to arrowCursor since the watch can only be displayed explicitly by your application.
CONST {Cursor Types }
arrowCursor =0; {the standard Macintosh arrow }
iBeamCursor =1; {text insertion I-beam }
crossCursor =2; {cross-hair }
plusCursor =3; {select cells in structured documents }
CursorTable specifies the cursor table number (from 1 to 255) that is deleted, along with its associated cursor zones. Any windows using the deleted table are reset such that they don’t reference a cursor table. If the cursor table does not exist, DeleteCursorTable does nothing.
CursorTable specifies the cursor table number (from 1 to 255) that is to be affected. If the cursor table does not exist, CursorZone does nothing.
Zone specifies the cursor zone number (from 1 to 255) within the table that is affected. If the zone already exists, it is deleted and recreated according to the values of the CursorZone procedure. If the zone does not exist, it is created. When Tools Plus references cursor zones, they are accessed sequentially starting at the lowest number. Therefore, if numerous zones exist, assign the most commonly used zones to the lowest numbers.
CursorType specifies the cursor shape for the zone. Window’s using this table display this type of cursor when the cursor enters this zone. If watchCursor is specified for this value, Tools Plus changes it to arrowCursor since the watch can only be displayed explicitly by your application.
Left, top, right, and Bottom define the zone’s size and location in a window. If the cursor’s location falls within these co-ordinates on the active window, it is said to be within the zone.
Also see: CursorZoneRect.
CONST {Cursor Types }
arrowCursor =0; {the standard Macintosh arrow }
iBeamCursor =1; {text insertion I-beam }
crossCursor =2; {cross-hair }
plusCursor =3; {select cells in structured documents }
CursorZoneRect is identical to the CursorZone procedure, except that it accepts the Bounds rectangle in place of the individual left, top, right and bottom co-ordinates.
CursorZoneRgn is identical to the CursorZone procedure, except that it accepts the ZoneRgn region handle in place of the individual left, top, right and bottom co-ordinates. CursorZoneRgn makes a copy of the region specified by the ZoneRgn handle, so you can dispose or alter the original region without affecting the cursor zone.
CursorTable specifies the cursor table number (from 1 to 255) that is affected. If the cursor table does not exist, DeleteCursorZone does nothing.
Zone specifies the cursor zone number (from 1 to 255) that is to be deleted within the table. If the zone does not exist, DeleteCursorZone does nothing.
CursorTable specifies the cursor table number (from 1 to 255) that is used.
Zone specifies the cursor zone number (from 1 to 255) within the table being queried.
Bounds returns the cursor zone’s bounding rectangle using the window’s local co-ordinates. If the specified zone does not exist in the specified table, Bounds returns as an empty rectangle with the co-ordinates (0,0,0,0).
function GetCursorZoneRgn (CursorTable, Zone: INTEGER): RGNHANDLE;
CursorTable specifies the cursor table number (from 1 to 255) that is used.
Zone specifies the cursor zone number (from 1 to 255) within the table being queried.
The function’s value returns a region handle to the cursor zone’s region using the window’s local co-ordinates. If the specified zone does not exist in the specified table, the function returns nil. Once you have obtained a region handle to a cursor zone, you may perform region operations on it, such as OffsetRgn, InsetRgn, MapRgn, etc. These operations will affect the related cursor zone. When you are finished making all the necessary changes, use ChangedCursorZone to inform Tools Plus that the cursor’s shape may have to be recalculated.
Note: Use this routine only to get a handle to a cursor zone’s region.
Do not initialize the receiving region handle variable by using
NewRgn (just create a variable that is a RgnHandle type). When
you have finished using the handle, do not use DisposeRgn.
Indicate that one or more cursor zone regions have been manually altered.
pascal void ChangedCursorZone (void);
procedure ChangedCursorZone;
If any cursor zone’s regions have been altered (by obtaining the cursor zone’s region handle and altering the region), you must call ChangedCursorZone. This procedure informs Tools Plus that the cursor’s shape may have to be recalculated because of cursor zone changes. Next time that PollSystem is called, the cursor’s shape is updated (if necessary).
Make the current window use a cursor table, or stop it from using any cursor table.
pascal void UseCursorTable (short CursorTable);
procedure UseCursorTable(CursorTable: INTEGER);
CursorTable specifies the cursor table number (from 1 to 255) that is used by the current window. If the current window does not belong to your application, if no windows are open, or if the cursor table does not exist, UseCursorTable does nothing. If CursorTable has a value of 0, the current window will stop using its present cursor table. The table, however, remains unaffected.
Determine which cursor zone contains a specified point in the current window.
pascal short FindCursorZone (Point thePoint);
function FindCursorZone(thePoint: POINT): INTEGER;
ThePoint is a location in the current window’s local co-ordinates.
The function’s value returns the cursor zone that contains the specified point. If the current window does not belong to your application, or if no windows are open, or if the current window does not use a cursor table, the function returns a value of zero (0). Zero will also be returned if the point is not contained in any cursor zone in the window’s cursor table.
This function ignores the placement of buttons, scroll bars, edit fields, list boxes, custom controls, etc. It reports strictly on the relationship between the provided point and the current window’s cursor table. If you obtained thePoint as a “mouse down” event from PollSystem’s doClick event, you can be sure that the click did not occur in button, scroll bar, edit field, list box or custom control.
Allow or disallow buttons to be clicked when the cursor is a wrist watch.
pascal void WatchCursorButtons (Boolean Allowed);
procedure WatchCursorButtons(Allowed: BOOLEAN);
Allowed specifies if buttons can be clicked on the active window while the wrist-watch cursor is displayed. With a value of true, push buttons can be clicked. With a value of false, they cannot. WatchCursorButtons is set to false when Tools Plus is initialized.
This feature is best used when a modal window is displayed with one or more push buttons while the Macintosh is busy with some lengthy process. Turn WatchCursorButtons on, then continue to call PollSystem during the process. This lets the user click a “Cancel” button, or to press Command-. to halt the process. Remember to turn WatchCursorButtons back off when you no longer need it, or else the watch cursor will be able to click any push buttons indiscriminately.
CONST {Click push buttons with watchCursor? }
on =true; {allow push buttons to be clicked when }
enabled =true; { the watchCursor is displayed. }
off =false; {do not allow push buttons to be clicked}
disabled=false; { when the watchCursor is displayed. }